	package VNF_DelaySBA_small;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

import com.net2plan.interfaces.networkDesign.Link;
import com.net2plan.interfaces.networkDesign.NetPlan;
import com.net2plan.interfaces.networkDesign.Node;

/**
 * 
 * @author shentianyu
 *
 *在大规模网络拓扑中对延时模型进行仿真，不再用n2p平台进行，直接在eclipse中跑
 *大体的过程：
 *1、生成对应的请求，放到一个集合中
 *2、按顺序取出请求，对请求中的VNF进行铺设
 *3、记录下最后网络的状态
 *
 */
public class Main {
	
	//存放请求的集合
	static List<NetPlan> requestList = new ArrayList<NetPlan>();
	static List<NetPlan> requestGroup = new ArrayList<NetPlan>();
	private static final int numberOfAllRequests = 10000;
	private static final int numberOfRequests = 10;
	public static int numberOfAllVNFTypes = 3;
	public static int numberOfAllSlot = 10 ;
	public static int numberOfCPU = 10;
	public static int numberOfDC = 3;
	static List<Integer> mfsiList = new ArrayList<Integer>();
	static List<Double> averageCostList = new ArrayList<Double>();
	static List<Integer> totalUsedCPUList = new ArrayList<Integer>();
	static List<Double> totalDelayTimeList = new ArrayList<Double>();

	public static void main(String[] args) {
		//生成请求
		for(int i=0;i<numberOfAllRequests;i++) {
			NetPlan request = CreateNetPlan.createOneNetplan();
			requestList.add(request);
		}
		//对请求进行铺设
		for(int k = 0;k<numberOfAllRequests; k++) {
			//每组仿真前，先对网络拓扑进行初始化
			if(k%numberOfRequests==0) {
				InitialNetPlan.initialNetplan();
			}
			String ch = new String() ;
			ch = "/Users/shentianyu/Net2Plan-0.4.0/workspace/data/networkTopologies/6nodes_16links.n2p";
			File f1 = new File(ch);
			NetPlan netplan = new NetPlan(f1);
			List<Node> subNodes = new ArrayList<Node>();
			System.out.println("start "+(k+1));
			NetPlan request = requestList.get(k);
			requestGroup.add(request);
			List<Link> requestLinks = request.getLinks(request.getNetworkLayerDefault());
			NodeMappingReturn nodeMappingReturn = new NodeMappingReturn();
			LinkMappingReturn linkMappingReturn = new LinkMappingReturn();
			nodeMappingReturn = MyUtil.nodeMapping(netplan, request);
			if(nodeMappingReturn.isSign()) {
				linkMappingReturn = MyUtil.linkMapping(netplan, request);
				if(linkMappingReturn.isSign()) {
					System.out.println("this request has been successfully served!");
				}
				else{
					System.out.println("linkmapping failed!");
				}
			}
			else {
				System.out.println("nodemapping failed!");
			}
			for(Link link:requestLinks) {
				System.out.print(link.getAttribute("pathlength"));
				System.out.println();
			}
			File f_1 = new File(ch);
			netplan.saveToFile(f_1);
			subNodes = netplan.getNodes();
			if(k%numberOfRequests==numberOfRequests-1) {
				//读数据,set DelayTime属性
				for(NetPlan thisRequest: requestGroup) {
					double delayTime = 0.0;
					for(Node node:thisRequest.getNodes()) {
						String vnfType = node.getAttribute("VNF");
						if(!"0".equals(vnfType)) {
							int subIndex = Integer.valueOf(node.getAttribute("MappedNode")).intValue();
							Node subNode = subNodes.get(subIndex);
							int numberOfThisVNF = Integer.valueOf(subNode.getAttribute(vnfType)).intValue();
							int vnf = Integer.valueOf(vnfType).intValue();
							delayTime+=(vnf+1)*5*numberOfThisVNF;
						}
					}
					double pathLength = 0.0;
					for(Link link:thisRequest.getLinks(thisRequest.getNetworkLayerDefault())) {
						pathLength+=Double.valueOf(link.getAttribute("pathlength")).doubleValue();
					}
					delayTime+=pathLength/200.0;
					thisRequest.setAttribute("DelayTime",String.valueOf(delayTime) );
				}
				double totalDelayTime = 0.0;
				double totalThreadTime = 0.0;
				for(NetPlan thisRequest: requestGroup) {
					totalDelayTime+=Double.valueOf(thisRequest.getAttribute("DelayTime")).doubleValue();
					totalThreadTime+=Double.valueOf(thisRequest.getAttribute("ThreadTime")).doubleValue();
				}
				netplan.setAttribute("TotalDelayTime", String.valueOf(totalDelayTime));
				netplan.setAttribute("TotalThreadTime", String.valueOf(totalThreadTime));
				requestGroup.clear();
				totalDelayTimeList.add(totalDelayTime);
				int mfsi = MyUtil.MFSI(netplan);
				netplan.setAttribute("MFSI", String.valueOf(mfsi));
				mfsiList.add(mfsi);
				int totalusedcpu = 0;
				for(Node node:subNodes) {
					if("1".equals(node.getAttribute("DataCenter"))) {
						System.out.println(" 数据中心"+subNodes.indexOf(node));
						for(int vnfType = 1;vnfType<=numberOfAllVNFTypes;vnfType++) {
							System.out.print(" VNF"+vnfType+": "+node.getAttribute(String.valueOf(vnfType))+",  ");
							int vnfNum = Integer.valueOf(node.getAttribute(String.valueOf(vnfType))).intValue();
							if(vnfNum>0) {
								totalusedcpu+=vnfType;
							}
						}
						System.out.println();
					}
				}
				totalUsedCPUList.add(totalusedcpu);
				netplan.setAttribute("TotalUsedCPU", String.valueOf(totalusedcpu));
				double averageCost =  totalDelayTime/totalThreadTime+(totalusedcpu*1.0)/(numberOfCPU*numberOfDC*1.0)+(mfsi*1.0)/(numberOfAllSlot*1.0);
				averageCostList.add(averageCost);
				netplan.setAttribute("AverageCost", String.valueOf(averageCost));
				
				System.out.println("TotalUsedCPU: "+netplan.getAttribute("TotalUsedCPU"));
				System.out.println("TotalDelayTime: "+netplan.getAttribute("TotalDelayTime"));
				System.out.println("TotalThreadTime: "+netplan.getAttribute("TotalThreadTime"));
				System.out.println("MFSI: "+netplan.getAttribute("MFSI"));
				System.out.println("AverageCost: "+netplan.getAttribute("AverageCost"));
			}
			if(k==numberOfAllRequests-1) {
				System.out.println("------------------------------------------------");
				System.out.print("TotalUsedCPU: ");
				for(Integer i:totalUsedCPUList) {
					System.out.print(i.intValue()+"  ");
				}
				System.out.println();
				
				System.out.print("MFSI: ");
				for(Integer i:mfsiList) {
					System.out.print(i.intValue()+"  ");
				}
				System.out.println();
				
				System.out.print("TotaoDelayTime: ");
				for(Double d:totalDelayTimeList) {
					System.out.print(String.format("%.6f", d.doubleValue())+"  ");
				}
				System.out.println();
				
				System.out.print("AverageCost: ");
				for(Double d:averageCostList) {
					System.out.print(String.format("%.6f", d.doubleValue())+"  ");
				}
				System.out.println();
				System.out.println();
				
				System.out.println("TotalUsedCPU avg: "+MyUtil.getAvgvalue(totalUsedCPUList));
				System.out.println("MFSI avg: "+MyUtil.getAvgvalue(mfsiList));
				System.out.println("TotalDelayTime avg: "+String.format("%.6f", MyUtil.getDoubleAvgvalue(totalDelayTimeList)));
				System.out.println("AverageCost avg: "+String.format("%.6f", MyUtil.getDoubleAvgvalue(averageCostList)));
			}
		}
	}
}
